package io.github.jsp.controller;

import io.github.jsp.cluster.ClusterManager;
import io.github.jsp.model.JobInfo;
import io.github.jsp.model.JobLog;
import io.github.jsp.model.JobRegistry;
import io.github.jsp.service.DistributedScheduleService;
import io.github.jsp.service.JobInfoService;
import io.github.jsp.service.JobLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class JobController {
    
    private static final Logger logger = LoggerFactory.getLogger(JobController.class);
    
    @Autowired
    private JobInfoService jobInfoService;
    
    @Autowired
    private JobLogService jobLogService;
    
    @Autowired
    private DistributedScheduleService scheduleService;
    
    @Autowired
    private ClusterManager clusterManager;
    
    @GetMapping("/jobs")
    public Map<String, Object> getJobs(@RequestParam(defaultValue = "1") int page,
                                       @RequestParam(defaultValue = "10") int size) {
        Map<String, Object> result = new HashMap<>();
        try {
            List<JobInfo> jobs = jobInfoService.getAll();
            result.put("code", 200);
            result.put("data", jobs);
            result.put("total", jobs.size());
        } catch (Exception e) {
            logger.error("Error getting jobs", e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @GetMapping("/jobs/{id}")
    public Map<String, Object> getJob(@PathVariable Integer id) {
        Map<String, Object> result = new HashMap<>();
        try {
            JobInfo job = jobInfoService.getById(id);
            if (job != null) {
                result.put("code", 200);
                result.put("data", job);
            } else {
                result.put("code", 404);
                result.put("msg", "Job not found");
            }
        } catch (Exception e) {
            logger.error("Error getting job: {}", id, e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @PostMapping("/jobs")
    public Map<String, Object> createJob(@RequestBody JobInfo jobInfo) {
        Map<String, Object> result = new HashMap<>();
        try {
            if (jobInfo.getJobGroup() == null) {
                jobInfo.setJobGroup("default");
            }
            if (jobInfo.getJobStatus() == null) {
                jobInfo.setJobStatus(1);
            }
            if (jobInfo.getTriggerStatus() == null) {
                jobInfo.setTriggerStatus(0);
            }
            if (jobInfo.getAuthor() == null) {
                jobInfo.setAuthor("admin");
            }
            if (jobInfo.getExecutorRouteStrategy() == null) {
                jobInfo.setExecutorRouteStrategy("FIRST");
            }
            if (jobInfo.getExecutorFailRetryCount() == null) {
                jobInfo.setExecutorFailRetryCount(0);
            }
            
            Integer jobId = jobInfoService.save(jobInfo);
            result.put("code", 200);
            result.put("data", jobId);
            result.put("msg", "Job created successfully");
        } catch (Exception e) {
            logger.error("Error creating job", e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @PutMapping("/jobs/{id}")
    public Map<String, Object> updateJob(@PathVariable Integer id, @RequestBody JobInfo jobInfo) {
        Map<String, Object> result = new HashMap<>();
        try {
            jobInfo.setId(id);
            int updated = jobInfoService.update(jobInfo);
            if (updated > 0) {
                scheduleService.rescheduleJob(jobInfo);
                result.put("code", 200);
                result.put("msg", "Job updated successfully");
            } else {
                result.put("code", 404);
                result.put("msg", "Job not found");
            }
        } catch (Exception e) {
            logger.error("Error updating job: {}", id, e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @DeleteMapping("/jobs/{id}")
    public Map<String, Object> deleteJob(@PathVariable Integer id) {
        Map<String, Object> result = new HashMap<>();
        try {
            scheduleService.unscheduleJob(id);
            int deleted = jobInfoService.deleteById(id);
            if (deleted > 0) {
                jobLogService.deleteByJobId(id);
                result.put("code", 200);
                result.put("msg", "Job deleted successfully");
            } else {
                result.put("code", 404);
                result.put("msg", "Job not found");
            }
        } catch (Exception e) {
            logger.error("Error deleting job: {}", id, e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @PostMapping("/jobs/{id}/start")
    public Map<String, Object> startJob(@PathVariable Integer id) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean started = scheduleService.startJob(id);
            if (started) {
                result.put("code", 200);
                result.put("msg", "Job started successfully");
            } else {
                result.put("code", 500);
                result.put("msg", "Failed to start job");
            }
        } catch (Exception e) {
            logger.error("Error starting job: {}", id, e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @PostMapping("/jobs/{id}/stop")
    public Map<String, Object> stopJob(@PathVariable Integer id) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean stopped = scheduleService.stopJob(id);
            if (stopped) {
                result.put("code", 200);
                result.put("msg", "Job stopped successfully");
            } else {
                result.put("code", 500);
                result.put("msg", "Failed to stop job");
            }
        } catch (Exception e) {
            logger.error("Error stopping job: {}", id, e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @GetMapping("/jobs/{id}/logs")
    public Map<String, Object> getJobLogs(@PathVariable Integer id,
                                          @RequestParam(defaultValue = "1") int page,
                                          @RequestParam(defaultValue = "10") int size) {
        Map<String, Object> result = new HashMap<>();
        try {
            List<JobLog> logs = jobLogService.getByJobIdWithPage(id, page, size);
            int total = jobLogService.getCountByJobId(id);
            result.put("code", 200);
            result.put("data", logs);
            result.put("total", total);
        } catch (Exception e) {
            logger.error("Error getting job logs: {}", id, e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @GetMapping("/logs")
    public Map<String, Object> getAllLogs(@RequestParam(defaultValue = "1") int page,
                                          @RequestParam(defaultValue = "10") int size) {
        Map<String, Object> result = new HashMap<>();
        try {
            List<JobLog> logs = jobLogService.getWithPage(page, size);
            int total = jobLogService.getTotalCount();
            result.put("code", 200);
            result.put("data", logs);
            result.put("total", total);
        } catch (Exception e) {
            logger.error("Error getting all logs", e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @GetMapping("/cluster/nodes")
    public Map<String, Object> getClusterNodes() {
        Map<String, Object> result = new HashMap<>();
        try {
            List<JobRegistry> nodes = clusterManager.getActiveNodes();
            result.put("code", 200);
            result.put("data", nodes);
            result.put("total", nodes != null ? nodes.size() : 0);
        } catch (Exception e) {
            logger.error("Error getting cluster nodes", e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
    
    @GetMapping("/system/info")
    public Map<String, Object> getSystemInfo() {
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, Object> info = new HashMap<>();
            info.put("activeNodes", clusterManager.getActiveNodeCount());
            info.put("totalJobs", jobInfoService.getAll().size());
            info.put("runningJobs", jobInfoService.getByTriggerStatus(1).size());
            
            result.put("code", 200);
            result.put("data", info);
        } catch (Exception e) {
            logger.error("Error getting system info", e);
            result.put("code", 500);
            result.put("msg", e.getMessage());
        }
        return result;
    }
}